package util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import processing.IndexGenerator;

public class InvertedIndex implements Serializable {

	private Hashtable<String, Entry> invIndex = new Hashtable<String,Entry>();

	public InvertedIndex() {
		
		try {
			System.out.println("Generating Inverted Index from Inv Index File...");
			generateInvIndexFromInvIndexFile();
		} catch (ClassNotFoundException | IOException e1) {
			System.out.println("Not Possible to Generate from Inv Index File");
		}
		
		if (this.invIndex == null) {
			try {
				System.out.println("Generating Inverted Index from Index File...");
				generateInvIndexFromIndexFile();
			} catch (ClassNotFoundException | IOException e) {
				System.out.println("Not Possible to Generate from Index File");
			}
		}

		if (this.invIndex == null) {

			System.out.println("Generating Inverted Index from Documents...");
			generateInvIndexFromDocuments();
		}

		ObjectOutputStream out = null;

		try {
			out = new ObjectOutputStream(new FileOutputStream(
					PathsAndConstants.invertedIndexPath));
			out.writeObject(this.invIndex);
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private void generateInvIndexFromInvIndexFile() throws FileNotFoundException, IOException, ClassNotFoundException {
		ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(
				PathsAndConstants.invertedIndexPath));
		
		this.invIndex = (Hashtable<String, Entry>) inputStream.readObject();
		
		inputStream.close();
	}

	private void generateInvIndexFromIndexFile() throws ClassNotFoundException, IOException {
		
		ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(
				PathsAndConstants.indexPath));
		
		Index index = (Index) inputStream.readObject();
		
		inputStream.close();
		
		this.invIndex = new Hashtable<String, Entry>();

		for (String key : index.getHashMap().keySet()) {
			this.invIndex.put(key,
					new Entry(index.getHashMap().get(key).size(), index.getHashMap().get(key)));
		}
	}
	
	private void generateInvIndexFromDocuments() {
		
		IndexGenerator indexGenerator = new IndexGenerator();
		indexGenerator.generateIndex();
		
		Index index = indexGenerator.getIndex();
		
		this.invIndex = new Hashtable<String, Entry>();
		
		for (String key : index.getHashMap().keySet()) {
			this.invIndex.put(key,
					new Entry(index.getHashMap().get(key).size(), index.getHashMap().get(key)));
		}
	}

	public Hashtable<String, Entry> getInvIndex() {
		return invIndex;
	}

	public void setInvIndex(Hashtable<String, Entry> invIndex) {
		this.invIndex = invIndex;
	}

	public List<String> getListOfTerms(){
		Enumeration<String> e = invIndex.keys();
		List<String> l = new ArrayList<String>();
		
		while( e.hasMoreElements() ){
			l.add(e.nextElement());
		}
		return l;
	}

	public Entry getEntry(String s){
		return invIndex.get(s);
	}
	
}
